home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / nethack.lha / nethack-3.1 / src / mhitu.c < prev    next >
C/C++ Source or Header  |  1993-01-22  |  56KB  |  2,160 lines

  1. /*    SCCS Id: @(#)mhitu.c    3.1    92/12/10    */
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include "hack.h"
  6. #include "artifact.h"
  7.  
  8. STATIC_VAR struct obj NEARDATA *otmp;
  9.  
  10. #ifdef POLYSELF
  11. STATIC_DCL void FDECL(urustm, (struct monst *, struct obj *));
  12. # ifdef OVL1
  13. static int FDECL(passiveum, (struct permonst *,struct monst *,struct attack *));
  14. # endif /* OVL1 */
  15. #endif /* POLYSELF */
  16.  
  17. #ifdef OVLB
  18. # ifdef SEDUCE
  19. static void FDECL(mayberem, (struct obj *, const char *));
  20. # endif
  21. #endif /* OVLB */
  22.  
  23. STATIC_DCL boolean FDECL(diseasemu, (struct permonst *));
  24. STATIC_DCL int FDECL(hitmu, (struct monst *,struct attack *));
  25. STATIC_DCL int FDECL(gulpmu, (struct monst *,struct attack *));
  26. STATIC_DCL int FDECL(explmu, (struct monst *,struct attack *,BOOLEAN_P));
  27. STATIC_DCL int FDECL(gazemu, (struct monst *,struct attack *));
  28. STATIC_DCL void FDECL(missmu,(struct monst *,BOOLEAN_P,struct attack *));
  29. STATIC_DCL void FDECL(mswings,(struct monst *,struct obj *));
  30. STATIC_DCL void FDECL(wildmiss,(struct monst *));
  31.  
  32. STATIC_DCL void FDECL(hurtarmor,(struct permonst *,int));
  33. STATIC_DCL void FDECL(hitmsg,(struct monst *,struct attack *));
  34.  
  35. /* See comment in mhitm.c.  If we use this a lot it probably should be */
  36. /* changed to a parameter to mhitu. */
  37. static int dieroll;
  38.  
  39. #ifdef OVL1
  40.  
  41.  
  42. STATIC_OVL void
  43. hitmsg(mtmp, mattk)
  44. register struct monst *mtmp;
  45. register struct attack *mattk;
  46. {
  47.     int compat;
  48.  
  49.     /* Note: if opposite gender, "seductively" */
  50.     /* If same gender, "engagingly" for nymph, normal msg for others */
  51.     if((compat = could_seduce(mtmp, &youmonst, mattk))
  52.             && !mtmp->mcan && !mtmp->mspec_used) {
  53.             pline("%s %s you %s.", Monnam(mtmp),
  54.             Blind ? "talks to" : "smiles at",
  55.             compat == 2 ? "engagingly" : "seductively");
  56.     } else
  57.         switch (mattk->aatyp) {
  58.         case AT_BITE:
  59.             pline("%s bites!", Monnam(mtmp));
  60.             break;
  61.         case AT_KICK:
  62. #ifdef POLYSELF
  63.             pline("%s kicks%c", Monnam(mtmp), thick_skinned(uasmon) ? '.' : '!');
  64. #else
  65.             pline("%s kicks!", Monnam(mtmp));
  66. #endif
  67.             break;
  68.         case AT_STNG:
  69.             pline("%s stings!", Monnam(mtmp));
  70.             break;
  71.         case AT_BUTT:
  72.             pline("%s butts!", Monnam(mtmp));
  73.             break;
  74.         case AT_TUCH:
  75.             pline("%s touches you!", Monnam(mtmp));
  76.             break;
  77.         case AT_TENT:
  78.             pline("%s tentacles suck you!", 
  79.                         s_suffix(Monnam(mtmp)));
  80.             break;
  81.         case AT_EXPL:
  82.             pline("%s explodes!", Monnam(mtmp));
  83.             break;
  84.         default:
  85.             pline("%s hits!", Monnam(mtmp));
  86.         }
  87. }
  88.  
  89. STATIC_OVL void
  90. missmu(mtmp, nearmiss, mattk)        /* monster missed you */
  91. register struct monst *mtmp;
  92. register boolean nearmiss;
  93. register struct attack *mattk;
  94. {
  95.     if(could_seduce(mtmp, &youmonst, mattk) && !mtmp->mcan)
  96.         pline("%s pretends to be friendly.", Monnam(mtmp));
  97.     else {
  98.         if (!flags.verbose || !nearmiss)
  99.         pline("%s misses.", Monnam(mtmp));
  100.         else
  101.         pline("%s just misses!", Monnam(mtmp));
  102.     }
  103. }
  104.  
  105. STATIC_OVL void
  106. mswings(mtmp, otemp)        /* monster swings obj */
  107. register struct monst *mtmp;
  108. register struct obj *otemp;
  109. {
  110.     if (!flags.verbose || Blind || !mon_visible(mtmp) ||
  111.         otemp->oclass != WEAPON_CLASS) return;
  112.     pline("%s %s %s %s.", Monnam(mtmp),
  113.           ((otemp->otyp >= SPEAR &&
  114.             otemp->otyp <= LANCE) ||
  115.            (otemp->otyp >= PARTISAN &&
  116.             otemp->otyp <= SPETUM) ||
  117.            otemp->otyp == TRIDENT) ? "thrusts" : "swings",
  118.           !humanoid(mtmp->data) ? "its" : mtmp->female ? "her" : "his",
  119.           xname(otemp));
  120. }
  121.  
  122. #endif /* OVL1 */
  123. #ifdef OVLB
  124.  
  125. STATIC_OVL void
  126. wildmiss(mtmp)        /* monster attacked your displaced image */
  127.     register struct monst *mtmp;
  128. {
  129.     int compat;
  130.  
  131.     if (!flags.verbose) return;
  132.     if (!cansee(mtmp->mx, mtmp->my)) return;
  133.         /* maybe it's attacking an image around the corner? */
  134.  
  135.     compat = could_seduce(mtmp, &youmonst, (struct attack *)0);
  136.         /* we really want to have the attack here to pass --
  137.          * the previous code checked whether mtmp was a nymph,
  138.          * which was not correct either since the attack type of
  139.          * succubi/incubi varies with SEDUCE
  140.          */
  141.  
  142.     if(Invis && !perceives(mtmp->data)) {
  143.         if(compat)
  144.         pline("%s tries to touch you and misses!", Monnam(mtmp));
  145.         else
  146.         switch(rn2(3)) {
  147.         case 0: pline("%s %s wildly and misses!", Monnam(mtmp),
  148.                   nolimbs(mtmp->data) ? "lunges" : "swings");
  149.             break;
  150.         case 1: pline("%s attacks a spot beside you.", Monnam(mtmp));
  151.             break;
  152.         case 2: pline("%s strikes at %s!", Monnam(mtmp),
  153.                 Underwater ? "empty water" : "thin air");
  154.             break;
  155.         default:pline("%s %s wildly!", Monnam(mtmp),
  156.                   nolimbs(mtmp->data) ? "lunges" : "swings");
  157.             break;
  158.         }
  159.     }
  160.     else if(Displaced) {
  161.         if(compat)
  162.         pline("%s smiles %s at your %sdisplaced image...",
  163.             Monnam(mtmp),
  164.             compat == 2 ? "engagingly" : "seductively",
  165.             Invis ? "invisible " : "");
  166.         else
  167.         pline("%s strikes at your %sdisplaced image and misses you!",
  168.             /* Note: if you're both invisible and displaced,
  169.              * only monsters which see invisible will attack your
  170.              * displaced image, since the displaced image is also
  171.              * invisible.
  172.              */
  173.             Monnam(mtmp),
  174.             Invis ? "invisible " : "");
  175.     }
  176.     /* monsters may miss especially on water level where
  177.        bubbles shake the player here and there */
  178.     else if(Underwater) {
  179.         if(compat)
  180.         pline("%s reaches towards your distorted image.",Monnam(mtmp));
  181.         else
  182.         pline("%s is fooled by water reflections and misses!",Monnam(mtmp));
  183.     }
  184.     else impossible("%s attacks you without knowing your location?",
  185.         Monnam(mtmp));
  186. }
  187.  
  188. void
  189. expels(mtmp, mdat, message)
  190. register struct monst *mtmp;
  191. register struct permonst *mdat; /* if mtmp is polymorphed, mdat != mtmp->data */
  192. boolean message;
  193. {
  194.     if (message) 
  195.         if (is_animal(mdat)) 
  196.             You("get regurgitated!");
  197.         else {
  198.             char blast[40];
  199.             register int i;
  200.  
  201.             blast[0] = '\0';
  202.             for(i = 0; i < NATTK; i++)
  203.                 if(mdat->mattk[i].aatyp == AT_ENGL) 
  204.                     break;
  205.             if (mdat->mattk[i].aatyp != AT_ENGL)
  206.                   impossible("Swallower has no engulfing attack?"); 
  207.             else {
  208.                 if (is_whirly(mdat)) {
  209.                     switch (mdat->mattk[i].adtyp) {
  210.                         case AD_ELEC:
  211.                             Strcpy(blast, 
  212.                               " in a shower of sparks");
  213.                             break;
  214.                         case AD_COLD:
  215.                             Strcpy(blast, 
  216.                             " in a blast of frost");
  217.                             break;
  218.                     }
  219.                 } else
  220.                     Strcpy(blast, " with a squelch");
  221.                 You("get expelled from %s%s!", 
  222.                     mon_nam(mtmp), blast);
  223.             }
  224.         }
  225.     unstuck(mtmp);    /* ball&chain returned in unstuck() */
  226.     mnexto(mtmp);
  227.     newsym(u.ux,u.uy);
  228.     spoteffects();
  229.     /* to cover for a case where mtmp is not in a next square */
  230.     if(um_dist(mtmp->mx,mtmp->my,1))
  231.         pline("Brrooaa...  You land hard at some distance.");
  232. }
  233.  
  234. #endif /* OVLB */
  235. #ifdef OVL0
  236.  
  237. /*
  238.  * mattacku: monster attacks you
  239.  *    returns 1 if monster dies (e.g. "yellow light"), 0 otherwise
  240.  *    Note: if you're displaced or invisible the monster might attack the
  241.  *        wrong position...
  242.  *    Assumption: it's attacking you or an empty square; if there's another
  243.  *        monster which it attacks by mistake, the caller had better
  244.  *        take care of it...
  245.  */
  246. int
  247. mattacku(mtmp)
  248.     register struct monst *mtmp;
  249. {
  250.     struct    attack    *mattk;
  251.     int    i, j, tmp, sum[NATTK];
  252.     struct    permonst *mdat = mtmp->data;
  253.     boolean ranged = (distu(mtmp->mx, mtmp->my) > 3);
  254.         /* Is it near you?  Affects your actions */
  255.     boolean range2 = !monnear(mtmp, mtmp->mux, mtmp->muy);
  256.         /* Does it think it's near you?  Affects its actions */
  257.     boolean foundyou = (mtmp->mux==u.ux && mtmp->muy==u.uy);
  258.         /* Is it attacking you or your image? */
  259.     boolean youseeit = canseemon(mtmp);
  260.         /* Might be attacking your image around the corner, or
  261.          * invisible, or you might be blind....
  262.          */
  263.  
  264.     if(!ranged) nomul(0);
  265.     if(mtmp->mhp <= 0 || (Underwater && !is_swimmer(mtmp->data)))
  266.         return(0);
  267.  
  268.     /* If swallowed, can only be affected by u.ustuck */
  269.     if(u.uswallow) {
  270.         if(mtmp != u.ustuck)
  271.         return(0);
  272.         u.ustuck->mux = u.ux;
  273.         u.ustuck->muy = u.uy;
  274.         range2 = 0;
  275.         foundyou = 1;
  276.         if(u.uinvulnerable) return (0); /* stomachs can't hurt you! */
  277.         /* This is not impossible! */
  278.         /* If the swallowing monster changes into a monster
  279.          * that is not capable of swallowing you, you get
  280.          * regurgitated - dgk
  281.          *
  282.          * This code is obsolete: newcham() will handle this contingency 
  283.          * as soon as it occurs in the course of a round. - kcd
  284.          *
  285.          * for(i = 0; i < NATTK; i++)
  286.          *     if(mdat->mattk[i].aatyp == AT_ENGL) goto doattack;
  287.          *
  288.          * You("get regurgitated!");
  289.          * regurgitates(mtmp);
  290.              * return(0);
  291.          */
  292.     }
  293. /* doattack:        use commented out above */
  294. #ifdef POLYSELF
  295.     if (u.uundetected && !range2 && foundyou && !u.uswallow) {
  296.         u.uundetected = 0;
  297.         if (is_hider(uasmon)) {
  298.             coord cc; /* maybe we need a unexto() function? */
  299.  
  300.             You("fall from the ceiling!");
  301.             if (enexto(&cc, u.ux, u.uy, &playermon)) {
  302.             remove_monster(mtmp->mx, mtmp->my);
  303.             newsym(mtmp->mx,mtmp->my);
  304.             place_monster(mtmp, u.ux, u.uy);
  305.             if(mtmp->wormno) worm_move(mtmp);
  306.             teleds(cc.x, cc.y);
  307.             set_apparxy(mtmp);
  308.             newsym(u.ux,u.uy);
  309.             } else {
  310.             pline("%s is killed by a falling %s (you)!",
  311.                         Monnam(mtmp), uasmon->mname);
  312.             killed(mtmp);
  313.             newsym(u.ux,u.uy);
  314.             return(0);
  315.             }
  316.             if (u.usym != S_PIERCER)
  317.             return(0);    /* trappers don't attack */
  318. #ifdef MUSE
  319.             if (which_armor(mtmp, WORN_HELMET)) {
  320. #else
  321.             if (is_mercenary(mtmp->data) && m_carrying(mtmp,HELMET)) {
  322. #endif
  323.             Your("blow glances off %s helmet.", 
  324.                            s_suffix(mon_nam(mtmp)));
  325.             } else {
  326.             if (3 + find_mac(mtmp) <= rnd(20)) {
  327.                 pline("%s is hit by a falling piercer (you)!",
  328.                                 Monnam(mtmp));
  329.                 if ((mtmp->mhp -= d(3,6)) < 1)
  330.                 killed(mtmp);
  331.             } else
  332.               pline("%s is almost hit by a falling piercer (you)!",
  333.                                 Monnam(mtmp));
  334.             }
  335.         } else {
  336.             if (!youseeit)
  337.             pline("It tries to move where you are hiding.");
  338.             else {
  339.             /* Ugly kludge for eggs.  The message is phrased so as
  340.              * to be directed at the monster, not the player,
  341.              * which makes "laid by you" wrong.  For the
  342.              * parallelism to work, we can't rephrase it, so we
  343.              * zap the "laid by you" momentarily instead.
  344.              */
  345.             struct obj *obj = level.objects[u.ux][u.uy];
  346.  
  347.             if (obj) {
  348.                 int save_spe = obj->spe;
  349.                 if (obj->otyp == EGG) obj->spe = 0;
  350.          pline("Wait, %s!  There's a %s named %s hiding under %s!",
  351.                 mtmp->mnamelth ? (const char *)NAME(mtmp)
  352.                            : mtmp->data->mname,
  353.                 uasmon->mname, plname,
  354.                 doname(level.objects[u.ux][u.uy]));
  355.                 obj->spe = save_spe;
  356.             } else
  357.                 impossible("hiding under nothing?");
  358.             }
  359.             newsym(u.ux,u.uy);
  360.         }
  361.         return(0);
  362.     }
  363.     if (u.usym == S_MIMIC_DEF && !range2 && foundyou && !u.uswallow) {
  364.         if (!youseeit) pline("It gets stuck on you.");
  365.             else pline("Wait, %s!  That's a %s named %s!",
  366.             mtmp->mnamelth ? (const char *)NAME(mtmp) : mtmp->data->mname,
  367.             uasmon->mname, plname);
  368.         u.ustuck = mtmp;
  369.         u.usym = S_MIMIC;
  370.         newsym(u.ux,u.uy);
  371.         return(0);
  372.     }
  373. #endif
  374. /*    Work out the armor class differential    */
  375.     tmp = u.uac + 10;        /* tmp ~= 0 - 20 */
  376. /*    give people with Ac < -9 at least some vulnerability */
  377. /*    negative AC gives an actual AC of somewhere from -1 to the AC */
  378.     if (tmp < 10) tmp = 10 - rnd(10-tmp);
  379.     tmp += mtmp->m_lev;
  380.     if(multi < 0) tmp += 4;
  381.     if((Invis && !perceives(mdat)) || !mtmp->mcansee)
  382.         tmp -= 2;
  383.     if(mtmp->mtrapped) tmp -= 2;
  384.     if(tmp <= 0) tmp = 1;
  385.  
  386.     /* make eels visible the moment they hit/miss us */
  387.     if(mdat->mlet == S_EEL && mtmp->minvis && cansee(mtmp->mx,mtmp->my)) {
  388.         mtmp->minvis = 0;
  389.         newsym(mtmp->mx,mtmp->my);
  390.     }
  391.  
  392. /*    Special demon handling code */
  393.     if(!mtmp->cham && is_demon(mdat) && !range2
  394.        && mtmp->data != &mons[PM_BALROG]
  395.        && mtmp->data != &mons[PM_SUCCUBUS]
  396.        && mtmp->data != &mons[PM_INCUBUS])
  397.         if(!mtmp->mcan && !rn2(13))    msummon(mdat);
  398.  
  399. /*    Special lycanthrope handling code */
  400.     if(!mtmp->cham && is_were(mdat) && !range2) {
  401.  
  402.         if(is_human(mdat)) {
  403.         if(!rn2(5 - (night() * 2)) && !mtmp->mcan) new_were(mtmp);
  404.         } else if(!rn2(30) && !mtmp->mcan) new_were(mtmp);
  405.  
  406.         if(!rn2(10) && !mtmp->mcan) {
  407.         if(youseeit) {
  408.             pline("%s summons help!",youseeit ?
  409.                 Monnam(mtmp) : "It");
  410.         } else
  411.             You("feel hemmed in.");
  412.         /* Technically wrong; we really should check if you can see the
  413.          * help, but close enough...
  414.          */
  415.         if (!were_summon(mdat,FALSE) && youseeit)
  416.             pline("But none comes.");
  417.         }
  418.     }
  419.  
  420.     if(u.uinvulnerable) {
  421.         /* monster's won't attack you */
  422.         if(mtmp == u.ustuck)
  423.         pline("%s loosens its grip slightly.", Monnam(mtmp));
  424.         else if(!range2) {
  425.         if(youseeit)
  426.             pline("%s starts to attack you, but pulls back.",
  427.               Monnam(mtmp));
  428.         else
  429.             You("feel something move nearby.");
  430.         }
  431.         return (0);
  432.     }
  433. #ifdef MUSE
  434.     /* Unlike defensive stuff, don't let them use item _and_ attack. */
  435.     /* Exception:  Medusa; her gaze is automatic.  (We actually kludge
  436.      * by permitting a full attack sequence, not just a gaze attack.)
  437.      */
  438.     if(find_offensive(mtmp)) {
  439.         int foo = use_offensive(mtmp);
  440.  
  441.         if (mtmp->data != &mons[PM_MEDUSA] && foo != 0) return(foo==1);
  442.     }
  443. #endif
  444.  
  445.     for(i = 0; i < NATTK; i++) {
  446.  
  447.         sum[i] = 0;
  448.         mattk = &(mdat->mattk[i]);
  449.         if (u.uswallow && (mattk->aatyp != AT_ENGL))
  450.         continue;
  451.         switch(mattk->aatyp) {
  452.         case AT_CLAW:    /* "hand to hand" attacks */
  453.         case AT_KICK:
  454.         case AT_BITE:
  455.         case AT_STNG:
  456.         case AT_TUCH:
  457.         case AT_BUTT:
  458.         case AT_TENT:
  459.             if(!range2) {
  460.                 if (foundyou) {
  461.                 if(tmp > (j = rnd(20+i))) {
  462. #ifdef POLYSELF
  463.                     if (mattk->aatyp != AT_KICK ||
  464.                         !thick_skinned(uasmon))
  465. #endif
  466.                     sum[i] = hitmu(mtmp, mattk);
  467.                 } else
  468.                     missmu(mtmp, (tmp == j), mattk);
  469.                 } else
  470.                 wildmiss(mtmp);
  471.             }
  472.             break;
  473.  
  474.         case AT_HUGS:    /* automatic if prev two attacks succeed */
  475.             /* Note: if displaced, prev attacks never succeeded */
  476.             if((!range2 && i>=2 && sum[i-1] && sum[i-2])
  477.                             || mtmp == u.ustuck)
  478.                 sum[i]= hitmu(mtmp, mattk);
  479.             break;
  480.  
  481.         case AT_GAZE:    /* can affect you either ranged or not */
  482.             if (youseeit)
  483.                 /* not displaced around a corner so not visible */
  484.                 sum[i] = gazemu(mtmp, mattk);
  485.             /* if gazemu returns, the player isn't dead.
  486.              * can't put this in gazemu() because youseeit might
  487.              * not be set
  488.              */
  489.             if(Reflecting && m_canseeu(mtmp) &&
  490.                !mtmp->mcan && mtmp->data == &mons[PM_MEDUSA]) {
  491.                 if(!Blind) {
  492.                 if(Reflecting & W_AMUL)
  493.                     makeknown(AMULET_OF_REFLECTION);
  494.                 else
  495.                     makeknown(SHIELD_OF_REFLECTION);
  496.                 pline("%s gaze is reflected by your %s.",
  497.                       s_suffix(Monnam(mtmp)),
  498.                       (Reflecting & W_AMUL) ?
  499.                       "medallion" : "shield");
  500.                 pline("%s is turned to stone!", Monnam(mtmp));
  501.                 }
  502.                 stoned = TRUE;
  503.                 killed(mtmp);
  504.                 sum[i] = 2;
  505.             }
  506.             break;
  507.  
  508.         case AT_EXPL:    /* automatic hit if next to, and aimed at you */
  509.             if(!range2) sum[i] = explmu(mtmp, mattk, foundyou);
  510.             break;
  511.  
  512.         case AT_ENGL:
  513.             if (!range2) {
  514.                 if(foundyou) {
  515.                 if(u.uswallow || tmp > (j = rnd(20+i))) {
  516.                     /* Force swallowing monster to be
  517.                      * displayed even when player is
  518.                      * moving away */
  519.                     flush_screen(1);
  520.                     sum[i] = gulpmu(mtmp, mattk);
  521.                 } else {
  522.                     missmu(mtmp, (tmp == j), mattk);
  523.                 }
  524.                            } else if (is_animal(mtmp->data))
  525.                     pline("%s gulps some air!", youseeit ?
  526.                           Monnam(mtmp) : "It");
  527.                   else
  528.                     if (youseeit)
  529.                      pline("%s lunges forward and recoils!",
  530.                            Monnam(mtmp));
  531.                     else
  532.                         You("hear a %s nearby.", 
  533.                             is_whirly(mtmp->data)? 
  534.                             "rushing noise" : 
  535.                             "splat");
  536.             }
  537.             break;
  538.         case AT_BREA:
  539.             if(range2) sum[i] = breamu(mtmp, mattk);
  540.             /* Note: breamu takes care of displacement */
  541.             break;
  542.         case AT_SPIT:
  543.             if(range2) sum[i] = spitmu(mtmp, mattk);
  544.             /* Note: spitmu takes care of displacement */
  545.             break;
  546.         case AT_WEAP:
  547.             if(range2) {
  548. #ifdef REINCARNATION
  549.                 if (!Is_rogue_level(&u.uz))
  550. #endif
  551.                     thrwmu(mtmp);
  552.             } else {
  553. #ifdef MUSE
  554.                 /* Rare but not impossible.  Normally the monster
  555.                  * wields when 2 spaces away, but it can be
  556.                  * teleported or whatever....
  557.                  */
  558.                 if (mtmp->weapon_check == NEED_WEAPON || !MON_WEP(mtmp)) {
  559.                 mtmp->weapon_check = NEED_HTH_WEAPON;
  560.                 /* mon_wield_item resets weapon_check as appropriate */
  561.                 if (mon_wield_item(mtmp) != 0) break;
  562.                 }
  563. #endif
  564.                 if (foundyou) {
  565.                 set_uasmon();
  566. #ifdef MUSE
  567.                 otmp = MON_WEP(mtmp);
  568. #else
  569.                 otmp = select_hwep(mtmp);
  570. #endif
  571.                 if(otmp) {
  572.                     tmp += hitval(otmp, uasmon);
  573.                     mswings(mtmp, otmp);
  574.                 }
  575.                 if(tmp > (j = dieroll = rnd(20+i)))
  576.                     sum[i] = hitmu(mtmp, mattk);
  577.                 else
  578.                     missmu(mtmp, (tmp == j), mattk);
  579.                 } else
  580.                 wildmiss(mtmp);
  581.             }
  582.             break;
  583.         case AT_MAGC:
  584.             if (range2)
  585.                 sum[i] = buzzmu(mtmp, mattk);
  586.             else
  587.                 if (foundyou)
  588.                 sum[i] = castmu(mtmp, mattk);
  589.                 else
  590.                 pline("%s casts a spell at thin air!",
  591.                     youseeit ? Monnam(mtmp) : "It");
  592.                 /* Not totally right since castmu allows other
  593.                  * spells, such as the monster healing itself,
  594.                  * that should work even when not next to you--
  595.                  * but the previous code was just as wrong.
  596.                  * --KAA
  597.                  */
  598.             break;
  599.  
  600.         default:        /* no attack */
  601.             break;
  602.         }
  603.         if(flags.botl) bot();
  604.         if(sum[i] == 2)  return(1);      /* attacker dead */
  605.         if(sum[i] == 3) break;  /* attacker teleported, no more attacks */
  606.         /* sum[i] == 1: successful attack */
  607.         /* sum[i] == 0: unsuccessful attack */
  608.     }
  609.     return(0);
  610. }
  611.  
  612. #endif /* OVL0 */
  613. #ifdef OVLB
  614.  
  615. /*
  616.  * helper function for some compilers that have trouble with hitmu
  617.  */
  618.  
  619. STATIC_OVL void
  620. hurtarmor(mdat, attk)
  621. struct permonst *mdat;
  622. int attk;
  623. {
  624.     boolean getbronze, rusting;
  625.     int    hurt;
  626.  
  627.     rusting = (attk == AD_RUST);
  628.     if (rusting) {
  629.         hurt = 1;
  630.         getbronze = (mdat == &mons[PM_BLACK_PUDDING] &&
  631.                  uarm && is_corrodeable(uarm));
  632.     }
  633.     else {
  634.         hurt=2;
  635.         getbronze = FALSE;
  636.     }
  637.     /* What the following code does: it keeps looping until it
  638.      * finds a target for the rust monster.
  639.      * Head, feet, etc... not covered by metal, or covered by
  640.      * rusty metal, are not targets.  However, your body always
  641.      * is, no matter what covers it.
  642.      */
  643.     while (1) {
  644.         switch(rn2(5)) {
  645.         case 0:
  646.         if (!rust_dmg(uarmh, rusting ? "helmet" : "leather helmet",
  647.                      hurt, FALSE))
  648.             continue;
  649.         break;
  650.         case 1:
  651.         if (uarmc) break;
  652.         /* Note the difference between break and continue;
  653.          * break means it was hit and didn't rust; continue
  654.          * means it wasn't a target and though it didn't rust
  655.          * something else did.
  656.          */
  657.         if (getbronze)
  658.             (void)rust_dmg(uarm, "bronze armor", 3, TRUE);
  659.         else if (uarm)
  660.             (void)rust_dmg(uarm, xname(uarm), hurt, TRUE);
  661.         break;
  662.         case 2:
  663.         if (!rust_dmg(uarms, rusting ? "shield" : "wooden shield",
  664.                      hurt, FALSE))
  665.             continue;
  666.         break;
  667.         case 3:
  668.         if (!rust_dmg(uarmg, rusting ? "metal gauntlets" : "gloves",
  669.                      hurt, FALSE))
  670.             continue;
  671.         break;
  672.         case 4:
  673.         if (!rust_dmg(uarmf, rusting ? "metal boots" : "boots",
  674.                      hurt, FALSE))
  675.             continue;
  676.         break;
  677.         }
  678.         break; /* Out of while loop */
  679.     }
  680. }
  681.  
  682. #endif /* OVLB */
  683. #ifdef OVL1
  684.  
  685. STATIC_OVL boolean
  686. diseasemu(mdat)
  687. struct permonst *mdat;
  688. {
  689.     if (defends(AD_DISE,uwep)
  690. #ifdef POLYSELF
  691.             || u.usym == S_FUNGUS
  692. #endif
  693.                         ) {
  694.         You("feel a slight illness.");
  695.         return FALSE;
  696.     } else {
  697.         if (!Sick) You("feel very sick.");
  698.         exercise(A_CON, FALSE);
  699.         make_sick(Sick + (long)rn1(25-ACURR(A_CON),15),FALSE);
  700.         u.usick_cause = mdat->mname;
  701.         return TRUE;
  702.     }
  703. }
  704.  
  705. /*
  706.  * hitmu: monster hits you
  707.  *      returns 2 if monster dies (e.g. "yellow light"), 1 otherwise
  708.  *      3 if the monster lives but teleported/paralyzed, so it can't keep
  709.  *           attacking you
  710.  */
  711. STATIC_OVL int
  712. hitmu(mtmp, mattk)
  713.     register struct monst *mtmp;
  714.     register struct attack  *mattk;
  715. {
  716.     register struct permonst *mdat = mtmp->data;
  717.     register int ctmp, ptmp;
  718.     int dmg, armpro;
  719.     char     buf[BUFSZ];
  720. #ifdef POLYSELF
  721.     struct permonst *olduasmon = uasmon;
  722.     int res;
  723. #endif
  724.  
  725. /*    If the monster is undetected & hits you.  You should know where
  726.  *    the attack came from.
  727.  */
  728.     if(mtmp->mundetected && hides_under(mdat)) {
  729.         mtmp->mundetected = 0;
  730.         if(!(Blind ? Telepat : (HTelepat & (WORN_HELMET|WORN_AMUL)))) {
  731.         register struct obj *obj;
  732.  
  733.         if(OBJ_AT(mtmp->mx, mtmp->my)) {
  734.             if((obj = level.objects[mtmp->mx][mtmp->my]) != 0)
  735.             pline("%s was hidden under %s!",
  736.                   Amonnam(mtmp), doname(obj));
  737.         }
  738.         newsym(mtmp->mx, mtmp->my);
  739.         }
  740.     }
  741.  
  742. /*    First determine the base damage done */
  743.     dmg = d((int)mattk->damn, (int)mattk->damd);
  744.     if(is_undead(mdat) && midnight())
  745.         dmg += d((int)mattk->damn, (int)mattk->damd); /* extra damage */
  746.  
  747. /*    Next a cancellation factor    */
  748. /*    Use ctmp when the cancellation factor takes into account certain
  749.  *    armor's special magic protection.  Otherwise just use !mtmp->mcan.
  750.  */
  751.     armpro = 0;
  752.     if (uarm && armpro < objects[uarm->otyp].a_can)
  753.         armpro = objects[uarm->otyp].a_can;
  754.     if (uarmc && armpro < objects[uarmc->otyp].a_can)
  755.         armpro = objects[uarmc->otyp].a_can;
  756.     ctmp = !mtmp->mcan && ((rn2(3) >= armpro) || !rn2(50));
  757.  
  758. /*    Now, adjust damages via resistances or specific attacks */
  759.     switch(mattk->adtyp) {
  760.         case AD_PHYS:
  761.         if(mattk->aatyp == AT_HUGS
  762. #ifdef POLYSELF
  763.                        && !sticks(uasmon)
  764. #endif
  765.                                 ) {
  766.             if(!u.ustuck && rn2(2)) {
  767.             u.ustuck = mtmp;
  768.             pline("%s grabs you!", Monnam(mtmp));
  769.             } else if(u.ustuck == mtmp) {
  770.                 exercise(A_STR, FALSE);
  771.             You("are being %s.",
  772.                   (mtmp->data == &mons[PM_ROPE_GOLEM])
  773.                   ? "choked" : "crushed");
  774.             }
  775.         } else {              /* hand to hand weapon */
  776.             if(mattk->aatyp == AT_WEAP && otmp) {
  777.             dmg += dmgval(otmp, uasmon);
  778.             if (dmg <= 0) dmg = 1;
  779.             if (!(otmp->oartifact &&
  780.                 artifact_hit(mtmp, &youmonst, otmp, &dmg,dieroll)))
  781.                  hitmsg(mtmp, mattk);
  782. #ifdef POLYSELF
  783.             if (u.mh > 1 && u.mh > ((u.uac>0) ? dmg : dmg+u.uac) &&
  784.                     (u.umonnum==PM_BLACK_PUDDING
  785.                     || u.umonnum==PM_BROWN_PUDDING)) {
  786.                 /* This redundancy necessary because you have to
  787.                  * take the damage _before_ being cloned.
  788.                  */
  789.                 if (u.uac < 0) dmg += u.uac;
  790.                 if (dmg < 1) dmg = 1;
  791.                 if (dmg > 1) exercise(A_STR, FALSE);
  792.                 u.mh -= dmg;
  793.                 flags.botl = 1;
  794.                 dmg = 0;
  795.                 if(cloneu())
  796.                 You("divide as %s hits you!",mon_nam(mtmp));
  797.             }
  798.             urustm(mtmp, otmp);
  799. #endif
  800.             } else
  801.             hitmsg(mtmp, mattk);
  802.         }
  803.         break;
  804.         case AD_DISE:
  805.         hitmsg(mtmp, mattk);
  806.         if (!diseasemu(mdat)) dmg = 0;
  807.         break;
  808.         case AD_FIRE:
  809.         hitmsg(mtmp, mattk);
  810.         if(ctmp) {
  811.             pline("You're on fire!");
  812.             if (Fire_resistance) {
  813.             pline("The fire doesn't feel hot!");
  814.             dmg = 0;
  815.             }
  816.             if((int) mtmp->m_lev > rn2(20))
  817.             destroy_item(SCROLL_CLASS, AD_FIRE);
  818.             if((int) mtmp->m_lev > rn2(20))
  819.             destroy_item(POTION_CLASS, AD_FIRE);
  820.             if((int) mtmp->m_lev > rn2(25))
  821.             destroy_item(SPBOOK_CLASS, AD_FIRE);
  822.         } else dmg = 0;
  823.         break;
  824.         case AD_COLD:
  825.         hitmsg(mtmp, mattk);
  826.         if(ctmp) {
  827.             pline("You're covered in frost!");
  828.             if (Cold_resistance) {
  829.             pline("The frost doesn't seem cold!");
  830.             dmg = 0;
  831.             }
  832.             if((int) mtmp->m_lev > rn2(20))
  833.             destroy_item(POTION_CLASS, AD_COLD);
  834.         } else dmg = 0;
  835.         break;
  836.         case AD_ELEC:
  837.         hitmsg(mtmp, mattk);
  838.         if(ctmp) {
  839.             You("get zapped!");
  840.             if (Shock_resistance) {
  841.             pline("The zap doesn't shock you!");
  842.             dmg = 0;
  843.             }
  844.             if((int) mtmp->m_lev > rn2(20))
  845.             destroy_item(WAND_CLASS, AD_ELEC);
  846.             if((int) mtmp->m_lev > rn2(20))
  847.             destroy_item(RING_CLASS, AD_ELEC);
  848.         } else dmg = 0;
  849.         break;
  850.         case AD_SLEE:
  851.         hitmsg(mtmp, mattk);
  852.         if(ctmp && multi >= 0 && !rn2(5)) {
  853.             if (Sleep_resistance) break;
  854.             nomul(-rnd(10));
  855.             u.usleep = 1;
  856.             nomovemsg = "You wake up.";
  857.             if (Blind)    You("are put to sleep!");
  858.             else    You("are put to sleep by %s!",mon_nam(mtmp));
  859.         }
  860.         break;
  861.         case AD_DRST:
  862.         ptmp = A_STR;
  863.         goto dopois;
  864.         case AD_DRDX:
  865.         ptmp = A_DEX;
  866.         goto dopois;
  867.         case AD_DRCO:
  868.         ptmp = A_CON;
  869. dopois:
  870.         hitmsg(mtmp, mattk);
  871.         if(ctmp && !rn2(8)) {
  872.             Sprintf(buf, "%s %s",
  873.                 !(canseemon(mtmp) || sensemon(mtmp)) ? "Its" :
  874.                 Hallucination ? s_suffix(rndmonnam()) : 
  875.                                 s_suffix(mdat->mname),
  876.                 (mattk->aatyp == AT_BITE) ? "bite" : "sting");
  877.             poisoned(buf, ptmp, mdat->mname, 30);
  878.         }
  879.         break;
  880.         case AD_DRIN:
  881.         hitmsg(mtmp, mattk);
  882.         if (defends(AD_DRIN, uwep)
  883. #ifdef POLYSELF
  884.                     || !has_head(uasmon)
  885. #endif
  886.                                 ) {
  887.             You("don't seem harmed.");
  888.             break;
  889.         }
  890.         if (uarmh && rn2(8)) {
  891.             Your("helmet blocks the attack to your head.");
  892.             break;
  893.         }
  894.         if (Half_physical_damage) dmg = (dmg+1) / 2;
  895.         losehp(dmg, mon_nam(mtmp), KILLED_BY_AN);
  896.         Your("brain is eaten!");
  897.         /* No such thing as mindless players... */
  898.         if (ABASE(A_INT) <= ATTRMIN(A_INT)) {
  899.             int lifesaved = 0;
  900.             while(1) {
  901.             if (lifesaved)
  902.                 pline("Unfortunately your brain is still gone.");
  903.             else
  904.                 Your("last thought fades away.");
  905.             killer = "brainlessness";
  906.             killer_format = KILLED_BY;
  907.             done(DIED);
  908.             lifesaved = 1;
  909. #ifdef WIZARD
  910.             if (wizard) break;
  911. #endif
  912.             }
  913.         }
  914.         (void) adjattrib(A_INT, -rnd(2), FALSE);
  915.         exercise(A_WIS, FALSE);
  916.         break;
  917.         case AD_PLYS:
  918.         hitmsg(mtmp, mattk);
  919.         if(ctmp && multi >= 0 && !rn2(3)) {
  920.             if (Blind)    You("are frozen!");
  921.             else    You("are frozen by %s!", mon_nam(mtmp));
  922.             nomul(-rnd(10));
  923.             exercise(A_DEX, FALSE);
  924.         }
  925.         break;
  926.         case AD_DRLI:
  927.         hitmsg(mtmp, mattk);
  928.         if (ctmp && !rn2(3)
  929. #ifdef POLYSELF
  930.             && !resists_drli(uasmon)
  931. #endif
  932.             && !defends(AD_DRLI, uwep)
  933.             ) losexp();
  934.         break;
  935.         case AD_LEGS:
  936.         { register long side = rn2(2) ? RIGHT_SIDE : LEFT_SIDE;
  937.           if (mtmp->mcan) {
  938.             pline("%s nuzzles against your %s %s!", Monnam(mtmp),
  939.               (side == RIGHT_SIDE) ? "right" : "left",
  940.               body_part(LEG));
  941.           } else {
  942.             if (uarmf) {
  943.             pline("%s scratches your %s boot!", Monnam(mtmp),
  944.                 (side == RIGHT_SIDE) ? "right" : "left");
  945.             break;
  946.             }
  947.             pline("%s pricks your %s %s!", Monnam(mtmp),
  948.               (side == RIGHT_SIDE) ? "right" : "left",
  949.               body_part(LEG));
  950.             set_wounded_legs(side, rnd(60-ACURR(A_DEX)));
  951.             exercise(A_STR, FALSE);
  952.             exercise(A_DEX, FALSE);
  953.           }
  954.           break;
  955.         }
  956.         case AD_STON:    /* at present only a cockatrice */
  957.         hitmsg(mtmp, mattk);
  958.         if(!rn2(3) && !Stoned) {
  959.             if (mtmp->mcan) {
  960.             if (flags.soundok)
  961.                 You("hear a cough from %s!", mon_nam(mtmp));
  962.             } else {
  963.             if (flags.soundok)
  964.                 You("hear %s hissing!", s_suffix(mon_nam(mtmp)));
  965.             if((!rn2(10) ||
  966.                 (flags.moonphase == NEW_MOON && !have_lizard()))
  967. #ifdef POLYSELF
  968.                 && !resists_ston(uasmon)
  969.                 && !(poly_when_stoned(uasmon) &&
  970.                  polymon(PM_STONE_GOLEM))
  971. #endif
  972.                 ) {
  973.                 Stoned = 5;
  974.                 return(1);
  975.                 /* You("turn to stone..."); */
  976.                 /* done_in_by(mtmp); */
  977.             }
  978.             }
  979.         }
  980.         break;
  981.         case AD_STCK:
  982.         hitmsg(mtmp, mattk);
  983.         if(ctmp && !u.ustuck
  984. #ifdef POLYSELF
  985.                      && !sticks(uasmon)
  986. #endif
  987.                             ) u.ustuck = mtmp;
  988.         break;
  989.         case AD_WRAP:
  990.         if(ctmp
  991. #ifdef POLYSELF
  992.             && !sticks(uasmon)
  993. #endif
  994.                       ) {
  995.             if(!u.ustuck && !rn2(10)) {
  996.             pline("%s swings itself around you!", Monnam(mtmp));
  997.             u.ustuck = mtmp;
  998.             } else if(u.ustuck == mtmp) {
  999.             if (is_pool(mtmp->mx,mtmp->my)
  1000. #ifdef POLYSELF
  1001.                 && !is_swimmer(uasmon)
  1002. #endif
  1003.                 && !Magical_breathing
  1004.                ) {
  1005.                 pline("%s drowns you....", Monnam(mtmp));
  1006.                 done(DROWNING);
  1007.             } else if(mattk->aatyp == AT_HUGS)
  1008.                 You("are being crushed.");
  1009.             } else {
  1010.             dmg = 0;
  1011.             if(flags.verbose)
  1012.                 pline("%s brushes against your %s.", Monnam(mtmp),
  1013.                    body_part(LEG));
  1014.             }
  1015.         } else dmg = 0;
  1016.         break;
  1017.         case AD_WERE:
  1018.         hitmsg(mtmp, mattk);
  1019. #ifdef POLYSELF
  1020.         if (ctmp && !rn2(4) && u.ulycn == -1
  1021.             && !Protection_from_shape_changers
  1022.             && !defends(AD_WERE,uwep)) {
  1023.             You("feel feverish.");
  1024.             exercise(A_CON, FALSE);
  1025.             u.ulycn = monsndx(mdat);
  1026.         }
  1027. #endif
  1028.         break;
  1029.         case AD_SGLD:
  1030.         hitmsg(mtmp, mattk);
  1031. #ifdef POLYSELF
  1032.         if (u.usym == mdat->mlet) break;
  1033. #endif
  1034.         if(!mtmp->mcan) stealgold(mtmp);
  1035.         break;
  1036.  
  1037.         case AD_SITM:    /* for now these are the same */
  1038.         case AD_SEDU:
  1039. #ifdef POLYSELF
  1040.         if (dmgtype(uasmon, AD_SEDU)
  1041. #  ifdef SEDUCE
  1042.             || dmgtype(uasmon, AD_SSEX)
  1043. #  endif
  1044.                         ) {
  1045.             if (mtmp->minvent)
  1046.     pline("%s brags about the goods some dungeon explorer provided.",
  1047.     Monnam(mtmp));
  1048.             else
  1049.     pline("%s makes some remarks about how difficult theft is lately.",
  1050.     Monnam(mtmp));
  1051.             rloc(mtmp);
  1052.             return 3;
  1053.         } else
  1054. #endif
  1055.         if(mtmp->mcan) {
  1056.             if (!Blind) {
  1057.             pline("%s tries to %s you, but you seem %s.",
  1058.                 Adjmonnam(mtmp, "plain"),
  1059.                 flags.female ? "charm" : "seduce",
  1060.                 flags.female ? "unaffected" : "uninterested");
  1061.             }
  1062.             if(rn2(3)) {
  1063.             rloc(mtmp);
  1064.             return 3;
  1065.             }
  1066.         } else {
  1067.             switch (steal(mtmp)) {
  1068.               case -1:
  1069.             return 2;
  1070.               case 0:
  1071.             break;
  1072.               default:
  1073.             rloc(mtmp);
  1074.             mtmp->mflee = 1;
  1075.             return 3;
  1076.             }
  1077.         }
  1078.         break;
  1079. #ifdef SEDUCE
  1080.         case AD_SSEX:
  1081.         if(could_seduce(mtmp, &youmonst, mattk) == 1
  1082.             && !mtmp->mcan)
  1083.             if (doseduce(mtmp))
  1084.             return 3;
  1085.         break;
  1086. #endif
  1087.         case AD_SAMU:
  1088.         hitmsg(mtmp, mattk);
  1089.         /* when the Wiz hits, 1/20 steals the amulet */
  1090.         if (!u.uhave.amulet) break;
  1091.         if (!rn2(20)) stealamulet(mtmp);
  1092.         break;
  1093.  
  1094.         case AD_TLPT:
  1095.         hitmsg(mtmp, mattk);
  1096.         if(ctmp) {
  1097.             if(flags.verbose)
  1098.             Your("position suddenly seems very uncertain!");
  1099.             tele();
  1100.         }
  1101.         break;
  1102.         case AD_RUST:
  1103.         hitmsg(mtmp, mattk);
  1104.         if (mtmp->mcan) break;
  1105. #if defined(POLYSELF)
  1106.         if (u.umonnum == PM_IRON_GOLEM) {
  1107.             You("rust!");
  1108.             rehumanize();
  1109.             break;
  1110.         }
  1111. #endif
  1112.         hurtarmor(mdat, AD_RUST);
  1113.         break;
  1114.         case AD_DCAY:
  1115.         hitmsg(mtmp, mattk);
  1116.         if (mtmp->mcan) break;
  1117. #if defined(POLYSELF)
  1118.         if (u.umonnum == PM_WOOD_GOLEM ||
  1119.             u.umonnum == PM_LEATHER_GOLEM) {
  1120.             You("rot!");
  1121.             rehumanize();
  1122.             break;
  1123.         }
  1124. #endif
  1125.         hurtarmor(mdat, AD_DCAY);
  1126.         break;
  1127.         case AD_HEAL:
  1128.         if(!uwep
  1129. #ifdef TOURIST
  1130.            && !uarmu
  1131. #endif
  1132.            && !uarm && !uarmh && !uarms && !uarmg && !uarmc && !uarmf) {
  1133.             pline("%s hits!  (I hope you don't mind.)", Monnam(mtmp));
  1134. #ifdef POLYSELF
  1135.             if (u.mtimedone) {
  1136.                 u.mh += rnd(7);
  1137.                 if(!rn2(7)) u.mhmax++;
  1138.                 if(u.mh > u.mhmax) u.mh = u.mhmax;
  1139.                 if(u.mh == u.mhmax && !rn2(50)) mongone(mtmp);
  1140.             } else {
  1141. #endif
  1142.                 u.uhp += rnd(7);
  1143.                 if(!rn2(7)) u.uhpmax++;
  1144.                 if(u.uhp > u.uhpmax) u.uhp = u.uhpmax;
  1145.                 if(u.uhp == u.uhpmax && !rn2(50)) mongone(mtmp);
  1146. #ifdef POLYSELF
  1147.             }
  1148. #endif
  1149.                 exercise(A_STR, TRUE);
  1150.                 exercise(A_CON, TRUE);
  1151.             flags.botl = 1;
  1152.             if(!rn2(50)) rloc(mtmp);
  1153.             dmg = 0;
  1154.         } else
  1155.             if(pl_character[0] == 'H') {
  1156.                 if (flags.soundok && !(moves % 5))
  1157.                 verbalize("Doc, I can't help you unless you cooperate.");
  1158.                 dmg = 0;
  1159.             } else hitmsg(mtmp, mattk);
  1160.         break;
  1161.         case AD_CURS:
  1162.         hitmsg(mtmp, mattk);
  1163.         if(!night() && mdat == &mons[PM_GREMLIN]) break;
  1164.         if(!mtmp->mcan && !rn2(10)) {
  1165.             if (flags.soundok)
  1166.             if (Blind) You("hear laughter.");
  1167.             else       pline("%s chuckles.", Monnam(mtmp));
  1168. #ifdef POLYSELF
  1169.             if (u.umonnum == PM_CLAY_GOLEM) {
  1170.             pline("Some writing vanishes from your head!");
  1171.             rehumanize();
  1172.             break;
  1173.             }
  1174. #endif
  1175.             attrcurse();
  1176.         }
  1177.         break;
  1178.         case AD_STUN:
  1179.         hitmsg(mtmp, mattk);
  1180.         if(!mtmp->mcan && !rn2(4)) {
  1181.             make_stunned(HStun + dmg, TRUE);
  1182.             dmg /= 2;
  1183.         }
  1184.         break;
  1185.         case AD_ACID:
  1186.         hitmsg(mtmp, mattk);
  1187.         if(!mtmp->mcan && !rn2(3))
  1188. #ifdef POLYSELF
  1189.             if (resists_acid(uasmon)) {
  1190.             pline("You're covered in acid, but it seems harmless.");
  1191.             dmg = 0;
  1192.             } else
  1193. #endif
  1194.               {
  1195.             pline("You're covered in acid!    It burns!");
  1196.             exercise(A_STR, FALSE);
  1197.               }
  1198.         else        dmg = 0;
  1199.         break;
  1200.         case AD_SLOW:
  1201.         hitmsg(mtmp, mattk);
  1202.         if(!ctmp && (Fast & (INTRINSIC|TIMEOUT)) &&
  1203.                     !defends(AD_SLOW, uwep) && !rn2(4)) {
  1204.             Fast &= ~(INTRINSIC|TIMEOUT);
  1205.             You("feel yourself slowing down.");
  1206.             exercise(A_DEX, FALSE);
  1207.         }
  1208.         break;
  1209.         case AD_DREN:
  1210.         hitmsg(mtmp, mattk);
  1211.         if(!ctmp && !rn2(4)) drain_en(dmg);
  1212.         dmg = 0;
  1213.         break;
  1214.         case AD_CONF:
  1215.         hitmsg(mtmp, mattk);
  1216.         if(!mtmp->mcan && !rn2(4) && !mtmp->mspec_used) {
  1217.             mtmp->mspec_used = mtmp->mspec_used + (dmg + rn2(6));
  1218.             if(Confusion)
  1219.              You("are getting even more confused.");
  1220.             else You("are getting confused.");
  1221.             make_confused(HConfusion + dmg, FALSE);
  1222.         }
  1223.         /* fall through to next case */
  1224.         case AD_DETH:
  1225.         pline("%s reaches out with its deadly touch.", Monnam(mtmp));
  1226. #ifdef POLYSELF
  1227.         if (is_undead(uasmon)) {
  1228.             /* Still does normal damage */
  1229.             pline("Was that the touch of death?");
  1230.             break;
  1231.         }
  1232. #endif
  1233.         if(!Antimagic && rn2(20) > 16)  {
  1234.             killer_format = KILLED_BY_AN;
  1235.             killer = "touch of death";
  1236.             done(DIED);
  1237.         } else {
  1238.             if(!rn2(5)) {
  1239.             if(Antimagic) shieldeff(u.ux, u.uy);
  1240.             pline("Lucky for you, it didn't work!");
  1241.             dmg = 0;
  1242.             } else You("feel your life force draining away...");
  1243.         }
  1244.         break;
  1245.         case AD_PEST:
  1246.         pline("%s reaches out, and you feel fever and chills.",
  1247.             Monnam(mtmp));
  1248.         (void) diseasemu(mdat); /* plus the normal damage */
  1249.         break;
  1250.         case AD_FAMN:
  1251.         pline("%s reaches out, and your body shrivels.",
  1252.             Monnam(mtmp));
  1253.         exercise(A_CON, FALSE);
  1254.         morehungry(rn1(40,40));
  1255.         /* plus the normal damage */
  1256.         break;
  1257.         default:    dmg = 0;
  1258.             break;
  1259.     }
  1260.     if(u.uhp < 1) done_in_by(mtmp);
  1261.  
  1262. /*    Negative armor class reduces damage done instead of fully protecting
  1263.  *    against hits.
  1264.  */
  1265.     if (dmg && u.uac < 0) {
  1266.         dmg -= rnd(-u.uac);
  1267.         if (dmg < 1) dmg = 1;
  1268.     }
  1269.  
  1270.     if(dmg) {
  1271.         if(Half_physical_damage)
  1272.         dmg = (dmg+1) / 2;
  1273. #ifdef MULDGN
  1274.         else if(pl_character[0] == 'P' && uwep && is_quest_artifact(uwep)
  1275.             && is_undead(mtmp->data))
  1276.         dmg = (dmg+1) / 2;
  1277. #endif
  1278.         mdamageu(mtmp, dmg);
  1279.     }
  1280.  
  1281. #ifdef POLYSELF
  1282.     res = passiveum(olduasmon, mtmp, mattk);
  1283.     stop_occupation();
  1284.     return res;
  1285. #else
  1286.     stop_occupation();
  1287.     return 1;
  1288. #endif
  1289. }
  1290.  
  1291. #endif /* OVL1 */
  1292. #ifdef OVLB
  1293.  
  1294. STATIC_OVL int
  1295. gulpmu(mtmp, mattk)    /* monster swallows you, or damage if u.uswallow */
  1296.     register struct monst *mtmp;
  1297.     register struct attack  *mattk;
  1298. {
  1299.     struct trap *t = t_at(u.ux, u.uy);
  1300.     int    tmp = d((int)mattk->damn, (int)mattk->damd);
  1301.     int    tim_tmp;
  1302.     register struct obj *otmp2;
  1303. #ifdef WALKIES
  1304.     int    i;
  1305. #endif
  1306.  
  1307.     if(!u.uswallow) {    /* swallows you */
  1308. #ifdef POLYSELF
  1309.         if (uasmon->msize >= MZ_HUGE) return(0);
  1310. #endif
  1311.         if ((t && ((t->ttyp == PIT) || (t->ttyp == SPIKED_PIT))) &&
  1312.             sobj_at(BOULDER, u.ux, u.uy))
  1313.             return(0);    
  1314.         if (Punished) unplacebc();    /* ball&chain go away */
  1315.         remove_monster(mtmp->mx, mtmp->my);
  1316.         place_monster(mtmp, u.ux, u.uy);
  1317.         u.ustuck = mtmp;
  1318.         newsym(mtmp->mx,mtmp->my);
  1319.         pline("%s engulfs you!", Monnam(mtmp));
  1320.         stop_occupation();
  1321.         if (u.utrap) {
  1322.             You("are released from the %s!",
  1323.                 u.utraptype==TT_WEB ? "web" : "trap");
  1324.             u.utrap = 0;
  1325.         }
  1326. #ifdef WALKIES
  1327.         if((i = number_leashed()) > 0) {
  1328.             pline("The leash%s snap%s loose...",
  1329.                     (i > 1) ? "es" : "",
  1330.                     (i > 1) ? "" : "s");
  1331.             unleash_all();
  1332.         }
  1333. #endif
  1334. #ifdef POLYSELF
  1335.         if (u.umonnum==PM_COCKATRICE && !resists_ston(mtmp->data)) {
  1336.             pline("%s turns to stone!", Monnam(mtmp));
  1337.             stoned = 1;
  1338.             xkilled(mtmp, 0);
  1339.             return 2;
  1340.         }
  1341. #endif
  1342.         display_nhwindow(WIN_MESSAGE, FALSE);
  1343.         vision_recalc(2);    /* hero can't see anything */
  1344.         u.uswallow = 1;
  1345.         /*assume that u.uswldtim always set >=0*/
  1346.         u.uswldtim = (tim_tmp =
  1347.             (-u.uac + 10 + rnd(25 - (int)mtmp->m_lev)) >> 1) > 0 ?
  1348.                 tim_tmp : 0;
  1349.         swallowed(1);
  1350.         for(otmp2 = invent; otmp2; otmp2 = otmp2->nobj) {
  1351.             (void) snuff_lit(otmp2);
  1352.         }
  1353.     } else {
  1354.  
  1355.         if(mtmp != u.ustuck) return(0);
  1356.         switch(mattk->adtyp) {
  1357.  
  1358.         case AD_DGST:
  1359.             if(!u.uswldtim) {    /* a3 *//*no cf unsigned <=0*/
  1360.             pline("%s totally digests you!", Monnam(mtmp));
  1361.             tmp = u.uhp;
  1362.             } else {
  1363.             pline("%s digests you!", Monnam(mtmp));
  1364.                 exercise(A_STR, FALSE);
  1365.             }
  1366.             break;
  1367.         case AD_PHYS:
  1368.             You("are pummeled with debris!");
  1369.             exercise(A_STR, FALSE);
  1370.             break;
  1371.         case AD_ACID:
  1372. #ifdef POLYSELF
  1373.             if (resists_acid(uasmon)) {
  1374.             You("are covered with a seemingly harmless goo.");
  1375.             tmp = 0;
  1376.             } else
  1377. #endif
  1378.             {
  1379.               if (Hallucination) pline("Ouch!  You've been slimed!");
  1380.               else You("are covered in slime!  It burns!");
  1381.               exercise(A_STR, FALSE);
  1382.             }
  1383.             break;
  1384.         case AD_BLND:
  1385.             if (!defends(AD_BLND, uwep)) {
  1386.             if(!Blind) {
  1387.                 You("can't see in here!");
  1388.                 make_blinded((long)tmp,FALSE);
  1389.             } else
  1390.                 /* keep him blind until disgorged */
  1391.                 make_blinded(Blinded+1,FALSE);
  1392.             }
  1393.             tmp = 0;
  1394.             break;
  1395.         case AD_ELEC:
  1396.             if(!mtmp->mcan && rn2(2)) {
  1397.             pline("The air around you crackles with electricity.");
  1398.             if (Shock_resistance) {
  1399.                 shieldeff(u.ux, u.uy);
  1400.                 You("seem unhurt.");
  1401. #if defined(POLYSELF)
  1402.                 ugolemeffects(AD_ELEC,tmp);
  1403. #endif
  1404.                 tmp = 0;
  1405.             }
  1406.             } else tmp = 0;
  1407.             break;
  1408.         case AD_COLD:
  1409.             if(!mtmp->mcan && rn2(2)) {
  1410.             if (Cold_resistance) {
  1411.                 shieldeff(u.ux, u.uy);
  1412.                 You("feel mildly chilly.");
  1413. #if defined(POLYSELF)
  1414.                 ugolemeffects(AD_COLD,tmp);
  1415. #endif
  1416.                 tmp = 0;
  1417.             } else You("are freezing to death!");
  1418.             } else tmp = 0;
  1419.             break;
  1420.         case AD_FIRE:
  1421.             if(!mtmp->mcan && rn2(2)) {
  1422.             if (Fire_resistance) {
  1423.                 shieldeff(u.ux, u.uy);
  1424.                 You("feel mildly hot.");
  1425. #if defined(POLYSELF)
  1426.                 ugolemeffects(AD_FIRE,tmp);
  1427. #endif
  1428.                 tmp = 0;
  1429.             } else You("are burning to a crisp!");
  1430.             } else tmp = 0;
  1431.             break;
  1432.         case AD_DISE:
  1433.             if (!diseasemu(mtmp->data)) tmp = 0;
  1434.             break;
  1435.         default:    tmp = 0;
  1436.                 break;
  1437.         }
  1438.     }
  1439.  
  1440.     if(Half_physical_damage) tmp = (tmp+1) / 2;
  1441.  
  1442.     mdamageu(mtmp, tmp);
  1443.     if(tmp) stop_occupation();
  1444.     if(u.uswldtim) --u.uswldtim;
  1445.     if(!u.uswldtim
  1446. #ifdef POLYSELF
  1447.         || u.umonnum==PM_COCKATRICE
  1448.         || uasmon->msize >= MZ_HUGE
  1449. #endif
  1450.         ) {
  1451. #ifdef POLYSELF
  1452.         if (u.umonnum == PM_COCKATRICE) {
  1453.         pline("%s very hurriedly %s you!", Monnam(mtmp), 
  1454.                is_animal(mtmp->data)? "regurgitates" : "expels");
  1455.         u.uswldtim = 0;
  1456.         } else {
  1457. #endif
  1458.         You("get %s!", 
  1459.             is_animal(mtmp->data)? "regurgitated" : "expelled");
  1460.         if(flags.verbose && is_animal(mtmp->data))
  1461.             pline("Obviously %s doesn't like your taste.",
  1462.                    mon_nam(mtmp));
  1463. #ifdef POLYSELF
  1464.         }
  1465. #endif
  1466.         expels(mtmp, mtmp->data, FALSE);
  1467.     }
  1468.     return(1);
  1469. }
  1470.  
  1471. STATIC_OVL int
  1472. explmu(mtmp, mattk, ufound)    /* monster explodes in your face */
  1473. register struct monst *mtmp;
  1474. register struct attack  *mattk;
  1475. boolean ufound;
  1476. {
  1477.     if (mtmp->mcan) return(0);
  1478.  
  1479.     if (!ufound)
  1480.     pline("%s explodes at a spot in thin air!",
  1481.           canseemon(mtmp) ? Monnam(mtmp) : "It");
  1482.     else {
  1483.     register int tmp = d((int)mattk->damn, (int)mattk->damd);
  1484.     register boolean not_affected = defends((int)mattk->adtyp, uwep);
  1485.  
  1486.     hitmsg(mtmp, mattk);
  1487.  
  1488.     switch (mattk->adtyp) {
  1489.         case AD_COLD:
  1490.         not_affected |= Cold_resistance;
  1491.  
  1492.         if (!not_affected) {
  1493.             if (flags.verbose) You("get blasted!");
  1494.             if (ACURR(A_DEX) > rnd(20)) {
  1495.             You("duck the blast...");
  1496.             tmp = (tmp+1) / 2;
  1497.             }
  1498.             if (Half_physical_damage) tmp = (tmp+1) / 2;
  1499.             mdamageu(mtmp, tmp);
  1500.         }
  1501.         break;
  1502.  
  1503.         case AD_BLND:
  1504.         not_affected |=
  1505. #ifdef POLYSELF
  1506.             (u.umonnum == PM_YELLOW_LIGHT) ||
  1507. #endif
  1508.             Blind;
  1509.         if (!not_affected) {
  1510.             if (mon_visible(mtmp)) {
  1511.             You("are blinded by a blast of light!");
  1512.             make_blinded((long)tmp, FALSE);
  1513.             } else
  1514.             You("get the impression it was not terribly bright.");
  1515.         }
  1516.         break;
  1517.  
  1518.         default:
  1519.         break;
  1520.     }
  1521.     if (not_affected) {
  1522.         You("seem unaffected by it.");
  1523. #if defined(POLYSELF)
  1524.         ugolemeffects((int)mattk->adtyp, tmp);
  1525. #endif
  1526.     }
  1527.     }
  1528.     mondead(mtmp);
  1529.     return(2);    /* it dies */
  1530. }
  1531.  
  1532. STATIC_OVL int
  1533. gazemu(mtmp, mattk)    /* monster gazes at you */
  1534.     register struct monst *mtmp;
  1535.     register struct attack  *mattk;
  1536. {
  1537.     switch(mattk->adtyp) {
  1538.         case AD_STON:
  1539.         if (mtmp->mcan) {
  1540.             You("notice that %s isn't all that ugly.",mon_nam(mtmp));
  1541.            break;
  1542.         }
  1543.         if (canseemon(mtmp)) {
  1544.             You("look upon %s.", mon_nam(mtmp));
  1545. # ifdef POLYSELF
  1546.             if (resists_ston(uasmon)) {
  1547.                 pline("So what?");
  1548.                 break;
  1549.             }
  1550.             if(poly_when_stoned(uasmon) && polymon(PM_STONE_GOLEM))
  1551.                 break;
  1552. # endif
  1553.             You("turn to stone...");
  1554.             killer_format = KILLED_BY_AN;
  1555.             killer = mons[PM_MEDUSA].mname;
  1556.             done(STONING);
  1557.             }
  1558.         break;
  1559.         case AD_CONF:
  1560.         if(!mtmp->mcan && canseemon(mtmp) && mtmp->mcansee && 
  1561.                     !mtmp->mspec_used && rn2(5)) {
  1562.             int conf = d(3,4);
  1563.  
  1564.             mtmp->mspec_used = mtmp->mspec_used + (conf + rn2(6));
  1565.             if(!Confusion)
  1566.             pline("%s gaze confuses you!", 
  1567.                               s_suffix(Monnam(mtmp)));
  1568.             else
  1569.             You("are getting more and more confused.");
  1570.             make_confused(HConfusion + conf, FALSE);
  1571.         }
  1572.         break;
  1573.         case AD_STUN:
  1574.         if(!mtmp->mcan && canseemon(mtmp) && mtmp->mcansee &&
  1575.                     !mtmp->mspec_used && rn2(5)) {
  1576.             int stun = d(2,6);
  1577.  
  1578.             pline("%s stares piercingly at you!", Monnam(mtmp));
  1579.             mtmp->mspec_used = mtmp->mspec_used + (stun + rn2(6));
  1580.             make_stunned(HStun + stun, TRUE);
  1581.         }
  1582.         break;
  1583.         case AD_BLND:
  1584.         if(!mtmp->mcan && canseemon(mtmp) && !defends(AD_BLND, uwep) &&
  1585.            distu(mtmp->mx,mtmp->my) <= BOLT_LIM*BOLT_LIM) {
  1586.             int blnd = d((int)mattk->damn, (int)mattk->damd);
  1587.             You("are blinded by %s radiance!", 
  1588.                           s_suffix(mon_nam(mtmp)));
  1589.             make_blinded((long)blnd,FALSE);
  1590.             make_stunned((long)d(1,3),TRUE);
  1591.         }
  1592.         break;
  1593.         default: impossible("Gaze attack %d?", mattk->adtyp);
  1594.         break;
  1595.     }
  1596.     return(1);
  1597. }
  1598.  
  1599. #endif /* OVLB */
  1600. #ifdef OVL1
  1601.  
  1602. void
  1603. mdamageu(mtmp, n)    /* mtmp hits you for n points damage */
  1604.     register struct monst *mtmp;
  1605.     register int n;
  1606. {
  1607. #ifdef POLYSELF
  1608.     if (u.mtimedone) {
  1609.         u.mh -= n;
  1610.         flags.botl = 1;
  1611.         if (u.mh < 1) rehumanize();
  1612.         return;
  1613.     }
  1614. #endif
  1615.     u.uhp -= n;
  1616.     flags.botl = 1;
  1617.     if(u.uhp < 1)
  1618.         done_in_by(mtmp);
  1619. }
  1620.  
  1621. #endif /* OVL1 */
  1622. #ifdef OVLB
  1623.  
  1624. #ifdef POLYSELF
  1625. STATIC_OVL void
  1626. urustm(mon, obj)
  1627. register struct monst *mon;
  1628. register struct obj *obj;
  1629. {
  1630.     boolean vis = cansee(mon->mx, mon->my);
  1631.  
  1632.     if (!mon || !obj) return; /* just in case */
  1633.     if (u.umonnum == PM_RUST_MONSTER && 
  1634.         is_rustprone(obj) && obj->oeroded < MAX_ERODE) {
  1635.         if (obj->greased || obj->oerodeproof || (obj->blessed && rn2(3))) {
  1636.             if (vis)
  1637.             pline("Somehow, %s weapon is not affected.",
  1638.                         s_suffix(mon_nam(mon)));
  1639.             if (obj->greased && !rn2(2)) obj->greased = 0;
  1640.         } else {
  1641.             if (vis)
  1642.             pline("%s %s%s!",
  1643.                     s_suffix(Monnam(mon)), aobjnam(obj, "rust"),
  1644.                     obj->oeroded ? " further" : "");
  1645.             obj->oeroded++;
  1646.         }
  1647.     }
  1648. }
  1649. #endif
  1650.  
  1651. #endif /* OVLB */
  1652. #ifdef OVL1
  1653.  
  1654. int
  1655. could_seduce(magr,mdef,mattk)
  1656. struct monst *magr, *mdef;
  1657. struct attack *mattk;
  1658. /* returns 0 if seduction impossible,
  1659.  *       1 if fine,
  1660.  *       2 if wrong gender for nymph */
  1661. {
  1662.     register struct permonst *pagr;
  1663.     boolean agrinvis, defperc;
  1664.     xchar genagr, gendef;
  1665.  
  1666.     if(magr == &youmonst) {
  1667.         pagr = uasmon;
  1668.         agrinvis = (Invis != 0);
  1669.         genagr = poly_gender();
  1670.     } else {
  1671.         pagr = magr->data;
  1672.         agrinvis = magr->minvis;
  1673.         genagr = gender(magr);
  1674.     }
  1675.     if(mdef == &youmonst) {
  1676.         defperc = (See_invisible != 0);
  1677.         gendef = poly_gender();
  1678.     } else {
  1679.         defperc = perceives(mdef->data);
  1680.         gendef = gender(mdef);
  1681.     }
  1682.  
  1683.     if(agrinvis && !defperc
  1684. #ifdef SEDUCE
  1685.         && mattk && mattk->adtyp != AD_SSEX
  1686. #endif
  1687.         )
  1688.         return 0;
  1689.  
  1690.     if(pagr->mlet != S_NYMPH
  1691.         && ((pagr != &mons[PM_INCUBUS] && pagr != &mons[PM_SUCCUBUS])
  1692. #ifdef SEDUCE
  1693.             || (mattk && mattk->adtyp != AD_SSEX)
  1694. #endif
  1695.            ))
  1696.         return 0;
  1697.     
  1698.     if(genagr == 1 - gendef)
  1699.         return 1;
  1700.     else
  1701.         return (pagr->mlet == S_NYMPH) ? 2 : 0;
  1702. }
  1703.  
  1704. #endif /* OVL1 */
  1705. #ifdef OVLB
  1706.  
  1707. #ifdef SEDUCE
  1708. /* Returns 1 if monster teleported */
  1709. int
  1710. doseduce(mon)
  1711. register struct monst *mon;
  1712. {
  1713.     register struct obj *ring;
  1714.     boolean fem = (mon->data == &mons[PM_SUCCUBUS]); /* otherwise incubus */
  1715.     char qbuf[QBUFSZ];
  1716.  
  1717.     if (mon->mcan || mon->mspec_used) {
  1718.           pline("%s acts as though %s has got a %sheadache.",
  1719.               Monnam(mon), Blind ? "it" : fem ? "she" : "he",
  1720.             mon->mcan ? "severe " : "");
  1721.         return 0;
  1722.     }
  1723.  
  1724.     if (unconscious()) {
  1725.         pline("%s seems dismayed at your lack of response.",
  1726.             Monnam(mon));
  1727.         return 0;
  1728.     }
  1729.  
  1730.     if (Blind) pline("It caresses you...");
  1731.     else You("feel very attracted to %s.", mon_nam(mon));
  1732.  
  1733.     for(ring = invent; ring; ring = ring->nobj) {
  1734.         if (ring->otyp != RIN_ADORNMENT) continue;
  1735.         if (fem) {
  1736.         if (rn2(20) < ACURR(A_CHA)) {
  1737.             Sprintf(qbuf, "\"That %s looks pretty.  May I have it?\"",
  1738.             xname(ring));
  1739.             makeknown(RIN_ADORNMENT);
  1740.             if (yn(qbuf) == 'n') continue;
  1741.         } else pline("%s decides she'd like your %s, and takes it.",
  1742.             Blind ? "She" : Monnam(mon), xname(ring));
  1743.         makeknown(RIN_ADORNMENT);
  1744.         if (ring==uleft || ring==uright) Ring_gone(ring);
  1745.         if (ring==uwep) setuwep((struct obj *)0);
  1746.         freeinv(ring);
  1747.         mpickobj(mon,ring);
  1748.         } else {
  1749.         char buf[BUFSZ];
  1750.  
  1751.         if (uleft && uright && uleft->otyp == RIN_ADORNMENT
  1752.                 && uright->otyp==RIN_ADORNMENT)
  1753.             break;
  1754.         if (ring==uleft || ring==uright) continue;
  1755.         if (rn2(20) < ACURR(A_CHA)) {
  1756.             Sprintf(qbuf,"\"That %s looks pretty.  Would you wear it for me?\"",
  1757.             xname(ring));
  1758.             makeknown(RIN_ADORNMENT);
  1759.             if (yn(qbuf) == 'n') continue;
  1760.         } else {
  1761.             pline("%s decides you'd look prettier wearing your %s,",
  1762.             Blind ? "He" : Monnam(mon), xname(ring));
  1763.             pline("and puts it on your finger.");
  1764.         }
  1765.         makeknown(RIN_ADORNMENT);
  1766.         if (!uright) {
  1767.             pline("%s puts %s on your right hand.",
  1768.             Blind ? "He" : Monnam(mon), the(xname(ring)));
  1769.             setworn(ring, RIGHT_RING);
  1770.         } else if (!uleft) {
  1771.             pline("%s puts %s on your left hand.",
  1772.             Blind ? "He" : Monnam(mon), the(xname(ring)));
  1773.             setworn(ring, LEFT_RING);
  1774.         } else if (uright && uright->otyp != RIN_ADORNMENT) {
  1775.             Strcpy(buf, xname(uright));
  1776.             pline("%s replaces your %s with your %s.",
  1777.             Blind ? "He" : Monnam(mon), buf, xname(ring));
  1778.             Ring_gone(uright);
  1779.             setworn(ring, RIGHT_RING);
  1780.         } else if (uleft && uleft->otyp != RIN_ADORNMENT) {
  1781.             Strcpy(buf, xname(uleft));
  1782.             pline("%s replaces your %s with your %s.",
  1783.             Blind ? "He" : Monnam(mon), buf, xname(ring));
  1784.             Ring_gone(uleft);
  1785.             setworn(ring, LEFT_RING);
  1786.         } else impossible("ring replacement");
  1787.         Ring_on(ring);
  1788.             prinv(NULL, ring, 0L);
  1789.         }
  1790.     }
  1791.  
  1792.     if (!uarmc && !uarmf && !uarmg && !uarms && !uarmh
  1793. #ifdef TOURIST
  1794.                                 && !uarmu
  1795. #endif
  1796.                                     )
  1797.         pline("%s murmurs sweet nothings into your ear.",
  1798.             Blind ? (fem ? "She" : "He") : Monnam(mon));
  1799.     else
  1800.         pline("%s murmurs in your ear, while helping you undress.",
  1801.             Blind ? (fem ? "She" : "He") : Monnam(mon));
  1802.     mayberem(uarmc, "cloak");
  1803.     if(!uarmc)
  1804.         mayberem(uarm, "suit");
  1805.     mayberem(uarmf, "boots");
  1806.     if(!uwep || !welded(uwep))
  1807.         mayberem(uarmg, "gloves");
  1808.     mayberem(uarms, "shield");
  1809.     mayberem(uarmh, "helmet");
  1810. #ifdef TOURIST
  1811.     if(!uarmc && !uarm)
  1812.         mayberem(uarmu, "shirt");
  1813. #endif
  1814.  
  1815.     if (uarm || uarmc) {
  1816.         verbalize("You're such a %s; I wish...",
  1817.                 flags.female ? "sweet lady" : "nice guy");
  1818.         rloc(mon);
  1819.         return 1;
  1820.     }
  1821.     if (u.ualign.type == A_CHAOTIC && u.ualign.record < ALIGNLIM)
  1822.         u.ualign.record++;
  1823.  
  1824.     /* by this point you have discovered mon's identity, blind or not... */
  1825.     pline("Time stands still while you and %s lie in each other's arms...",
  1826.         mon_nam(mon));
  1827.     if (rn2(35) > ACURR(A_CHA) + ACURR(A_INT)) {
  1828.         /* Don't bother with mspec_used here... it didn't get tired! */
  1829.         pline("%s seems to have enjoyed it more than you...",
  1830.             Monnam(mon));
  1831.         switch (rn2(5)) {
  1832.             case 0: You("feel drained of energy.");
  1833.                 u.uen = 0;
  1834.                 u.uenmax -= rnd(Half_physical_damage ? 5 : 10);
  1835.                     exercise(A_CON, FALSE);
  1836.                 if (u.uenmax < 0) u.uenmax = 0;
  1837.                 break;
  1838.             case 1: You("are down in the dumps.");
  1839.                 (void) adjattrib(A_CON, -1, TRUE);
  1840.                     exercise(A_CON, FALSE);
  1841.                 flags.botl = 1;
  1842.                 break;
  1843.             case 2: Your("senses are dulled.");
  1844.                 (void) adjattrib(A_WIS, -1, TRUE);
  1845.                     exercise(A_WIS, FALSE);
  1846.                 flags.botl = 1;
  1847.                 break;
  1848.             case 3:
  1849. #ifdef POLYSELF
  1850.                 if (resists_drli(uasmon))
  1851.                     You("have a curious feeling...");
  1852.                 else {
  1853. #endif
  1854.                     You("feel out of shape.");
  1855.                     losexp();
  1856.                     if(u.uhp <= 0) {
  1857.                     killer_format = KILLED_BY;
  1858.                     killer = "overexertion";
  1859.                     done(DIED);
  1860.                     }
  1861. #ifdef POLYSELF
  1862.                 }
  1863. #endif
  1864.                 break;
  1865.             case 4: {
  1866.                 int tmp;
  1867.                 You("feel exhausted.");
  1868.                     exercise(A_STR, FALSE);
  1869.                 tmp = rn1(10, 6);
  1870.                 if(Half_physical_damage) tmp = (tmp+1) / 2;
  1871.                 losehp(tmp, "exhaustion", KILLED_BY);
  1872.                 break;
  1873.             }
  1874.         }
  1875.     } else {
  1876.         mon->mspec_used = rnd(100); /* monster is worn out */
  1877.         You("seem to have enjoyed it more than %s...", mon_nam(mon));
  1878.         switch (rn2(5)) {
  1879.             case 0: You("feel raised to your full potential.");
  1880.                     exercise(A_CON, TRUE);
  1881.                 u.uen = (u.uenmax += rnd(5));
  1882.                 break;
  1883.             case 1: You("feel good enough to do it again.");
  1884.                 (void) adjattrib(A_CON, 1, TRUE);
  1885.                     exercise(A_CON, TRUE);
  1886.                 flags.botl = 1;
  1887.                 break;
  1888.             case 2: You("will always remember %s...", mon_nam(mon));
  1889.                 (void) adjattrib(A_WIS, 1, TRUE);
  1890.                     exercise(A_WIS, TRUE);
  1891.                 flags.botl = 1;
  1892.                 break;
  1893.             case 3: pline("That was a very educational experience.");
  1894.                 pluslvl();
  1895.                     exercise(A_WIS, TRUE);
  1896.                 break;
  1897.             case 4: You("feel restored to health!");
  1898.                 u.uhp = u.uhpmax;
  1899. #ifdef POLYSELF
  1900.                 if (u.mtimedone) u.mh = u.mhmax;
  1901. #endif
  1902.                     exercise(A_STR, TRUE);
  1903.                 flags.botl = 1;
  1904.                 break;
  1905.         }
  1906.     }
  1907.  
  1908.     if (mon->mtame) /* don't charge */ ;
  1909.     else if (rn2(20) < ACURR(A_CHA)) {
  1910.         pline("%s demands that you pay %s, but you refuse...",
  1911.             Monnam(mon), (fem ? "her" : "him"));
  1912.     }
  1913. #ifdef POLYSELF
  1914.     else if (u.umonnum == PM_LEPRECHAUN)
  1915.         pline("%s tries to take your money, but fails...",
  1916.                 Monnam(mon));
  1917. #endif
  1918.     else {
  1919.         long cost;
  1920.  
  1921.         if (u.ugold > (long)LARGEST_INT - 10L)
  1922.             cost = (long) rnd(LARGEST_INT) + 500L;
  1923.         else
  1924.             cost = (long) rnd((int)u.ugold + 10) + 500L;
  1925.         if (mon->mpeaceful) {
  1926.             cost /= 5L;
  1927.             if (!cost) cost = 1L;
  1928.         }
  1929.         if (cost > u.ugold) cost = u.ugold;
  1930.         if (!cost) verbalize("It's on the house!");
  1931.         else {
  1932.             pline("%s takes %ld zorkmid%s for services rendered!",
  1933.                 Monnam(mon), cost, plur(cost));
  1934.             u.ugold -= cost;
  1935.             mon->mgold += cost;
  1936.             flags.botl = 1;
  1937.         }
  1938.     }
  1939.     if (!rn2(25)) mon->mcan = 1; /* monster is worn out */
  1940.     rloc(mon);
  1941.     return 1;
  1942. }
  1943.  
  1944. static void
  1945. mayberem(obj, str)
  1946. register struct obj *obj;
  1947. const char *str;
  1948. {
  1949.     char qbuf[QBUFSZ];
  1950.  
  1951.     if (!obj || !obj->owornmask) return;
  1952.  
  1953.     if (rn2(20) < ACURR(A_CHA)) {
  1954.         Sprintf(qbuf,"\"Shall I remove your %s, %s?\"",
  1955.             str,
  1956.             (!rn2(2) ? "lover" : !rn2(2) ? "dear" : "sweetheart"));
  1957.         if (yn(qbuf) == 'n') return;
  1958.     } else verbalize("Take off your %s; %s.", str,
  1959.             (obj == uarm)  ? "let's get a little closer" :
  1960.             (obj == uarmc || obj == uarms) ? "it's in the way" :
  1961.             (obj == uarmf) ? "let me rub your feet" :
  1962.             (obj == uarmg) ? "they're too clumsy" :
  1963. #ifdef TOURIST
  1964.             (obj == uarmu) ? "let me massage you" :
  1965. #endif
  1966.             /* obj == uarmh */
  1967.             "let me run my fingers through your hair");
  1968.  
  1969.     if (donning(obj)) cancel_don();
  1970.     if (obj == uarm)  (void) Armor_off();
  1971.     else if (obj == uarmc) (void) Cloak_off();
  1972.     else if (obj == uarmf) (void) Boots_off();
  1973.     else if (obj == uarmg) (void) Gloves_off();
  1974.     else if (obj == uarmh) (void) Helmet_off();
  1975.     else setworn((struct obj *)0, obj->owornmask & W_ARMOR);
  1976. }
  1977. #endif  /* SEDUCE */
  1978.  
  1979. #endif /* OVLB */
  1980.  
  1981. #ifdef POLYSELF
  1982.  
  1983. #ifdef OVL1
  1984.  
  1985. static int
  1986. passiveum(olduasmon,mtmp,mattk)
  1987. struct permonst *olduasmon;
  1988. register struct monst *mtmp;
  1989. register struct attack *mattk;
  1990. {
  1991.     register struct permonst *mdat = mtmp->data;
  1992.     int i, tmp;
  1993.  
  1994.     for(i = 0; ; i++) {
  1995.         if(i >= NATTK) return 1;
  1996.         if(olduasmon->mattk[i].aatyp == AT_NONE) break;
  1997.     }
  1998.     if (olduasmon->mattk[i].damn)
  1999.         tmp = d((int)olduasmon->mattk[i].damn, 
  2000.                                     (int)olduasmon->mattk[i].damd);
  2001.     else if(olduasmon->mattk[i].damd)
  2002.         tmp = d((int)olduasmon->mlevel+1, (int)olduasmon->mattk[i].damd);
  2003.     else
  2004.         tmp = 0;
  2005.  
  2006.     /* These affect the enemy even if you were "killed" (rehumanized) */
  2007.     switch(olduasmon->mattk[i].adtyp) {
  2008.         case AD_ACID:
  2009.         if (!rn2(2)) {
  2010.             pline("%s is splashed by your acid!", Monnam(mtmp));
  2011.             if(resists_acid(mdat)) {
  2012.             pline("%s is not affected.", Monnam(mtmp));
  2013.             tmp = 0;
  2014.             }
  2015.         } else tmp = 0;
  2016.         goto assess_dmg;
  2017.         case AD_STON: /* cockatrice */
  2018.         if (!resists_ston(mdat) &&
  2019. #ifdef MUSE
  2020.             (mattk->aatyp != AT_WEAP || !MON_WEP(mtmp)) &&
  2021. #else
  2022.             (mattk->aatyp != AT_WEAP || !select_hwep(mtmp)) &&
  2023. #endif
  2024.             mattk->aatyp != AT_GAZE && mattk->aatyp != AT_EXPL &&
  2025.             mattk->aatyp != AT_MAGC &&
  2026. #ifdef MUSE
  2027.             (!which_armor(mtmp, W_ARMG))) {
  2028. #else
  2029.             (!is_mercenary(mdat) ||
  2030.                       !m_carrying(mtmp, LEATHER_GLOVES))) {
  2031. #endif
  2032.             if(poly_when_stoned(mdat)) {
  2033.             mon_to_stone(mtmp);
  2034.             return (1);
  2035.             }
  2036.             pline("%s turns to stone!", Monnam(mtmp));
  2037.             stoned = 1;
  2038.             xkilled(mtmp, 0);
  2039.             return 2;
  2040.         }
  2041.         return 1;
  2042.         default:
  2043.         break;
  2044.     }
  2045.     if (!u.mtimedone) return 1;
  2046.  
  2047.     /* These affect the enemy only if you are still a monster */
  2048.     if (rn2(3)) switch(uasmon->mattk[i].adtyp) {
  2049.         case AD_PLYS: /* Floating eye */
  2050.         if (u.umonnum == PM_FLOATING_EYE) {
  2051.             if (!rn2(4)) tmp = 120;
  2052.             if (mtmp->mcansee && haseyes(mtmp->data) && rn2(3) &&
  2053.                 (perceives(mdat) || !Invis)) {
  2054.             if (Blind)
  2055.                 pline("As a blind %s, you cannot defend yourself.",
  2056.                             uasmon->mname);
  2057.                 else {
  2058.                 pline("%s is frozen by your gaze!", Monnam(mtmp));
  2059.                 mtmp->mcanmove = 0;
  2060.                 mtmp->mfrozen = tmp;
  2061.                 return 3;
  2062.             }
  2063.             }
  2064.         } else { /* gelatinous cube */
  2065.             pline("%s is frozen by you.", Monnam(mtmp));
  2066.             mtmp->mcanmove = 0;
  2067.             mtmp->mfrozen = tmp;
  2068.             return 3;
  2069.         }
  2070.         return 1;
  2071.         case AD_COLD: /* Brown mold or blue jelly */
  2072.         if(resists_cold(mdat)) {
  2073.               shieldeff(mtmp->mx, mtmp->my);
  2074.             pline("%s is mildly chilly.", Monnam(mtmp));
  2075.             golemeffects(mtmp, AD_COLD, tmp);
  2076.             tmp = 0;
  2077.             break;
  2078.         }
  2079.         pline("%s is suddenly very cold!", Monnam(mtmp));
  2080.         u.mh += tmp / 2;
  2081.         if (u.mhmax < u.mh) u.mhmax = u.mh;
  2082.         if (u.mhmax > ((uasmon->mlevel+1) * 8)) {
  2083.             register struct monst *mon;
  2084.  
  2085.             if ((mon = cloneu()) != 0) {
  2086.                 mon->mhpmax = u.mhmax /= 2;
  2087.                 You("multiply from %s heat!", 
  2088.                            s_suffix(mon_nam(mtmp)));
  2089.             }
  2090.         }
  2091.         break;
  2092.         case AD_STUN: /* Yellow mold */
  2093.         if (!mtmp->mstun) {
  2094.             mtmp->mstun = 1;
  2095.             pline("%s staggers.", Monnam(mtmp));
  2096.         }
  2097.         tmp = 0;
  2098.         break;
  2099.         case AD_FIRE: /* Red mold */
  2100.         if(resists_fire(mdat)) {
  2101.               shieldeff(mtmp->mx, mtmp->my);
  2102.             pline("%s is mildly warm.", Monnam(mtmp));
  2103.             golemeffects(mtmp, AD_FIRE, tmp);
  2104.             tmp = 0;
  2105.             break;
  2106.         }
  2107.         pline("%s is suddenly very hot!", Monnam(mtmp));
  2108.         break;
  2109.         case AD_ELEC:
  2110.         if(resists_elec(mdat)) {
  2111.               shieldeff(mtmp->mx, mtmp->my);
  2112.             pline("%s is slightly tingled.", Monnam(mtmp));
  2113.             golemeffects(mtmp, AD_ELEC, tmp);
  2114.             tmp = 0;
  2115.             break;
  2116.         }
  2117.         pline("%s is jolted with your electricity!", Monnam(mtmp));
  2118.         break;
  2119.         default: tmp = 0;
  2120.         break;
  2121.     }
  2122.     else tmp = 0;
  2123.  
  2124.     assess_dmg:
  2125.     if((mtmp->mhp -= tmp) <= 0) {
  2126.         pline("%s dies!", Monnam(mtmp));
  2127.         xkilled(mtmp,0);
  2128.         return 2;
  2129.     }
  2130.     return 1;
  2131. }
  2132.  
  2133. #endif /* OVL1 */
  2134. #ifdef OVLB
  2135.  
  2136. #include "edog.h"
  2137. struct monst *
  2138. cloneu()
  2139. {
  2140.     register struct monst *mon;
  2141.  
  2142.     if (u.mh <= 1) return(struct monst *)0;
  2143.     if (uasmon->geno & G_EXTINCT) return(struct monst *)0;
  2144.     uasmon->pxlth += sizeof(struct edog);
  2145.     mon = makemon(uasmon, u.ux, u.uy);
  2146.     uasmon->pxlth -= sizeof(struct edog);
  2147.     mon = christen_monst(mon, plname);
  2148.     initedog(mon);
  2149.     mon->m_lev = uasmon->mlevel;
  2150.     mon->mhp = u.mh /= 2;
  2151.     mon->mhpmax = u.mhmax;
  2152.     return(mon);
  2153. }
  2154.  
  2155. #endif /* OVLB */
  2156.  
  2157. #endif /* POLYSELF */
  2158.  
  2159. /*mhitu.c*/
  2160.